#pragma semicolon 1
#include <sourcemod>
#include <cstrike>
#include <sdkhooks>
#include <sdktools>
#include <colors>
#include <cstrike>
#include <PowerupsX>

#define PREFIX "{olive}PowerupsX {default}>{green} "
new AbilityHax;
#define HEALAMOUNT 15

new bool:AbilityHaxUse[MAXPLAYERS+1];
new Handle:AbilityHaxTimer[MAXPLAYERS + 1] = {INVALID_HANDLE,...};

new Float:HaxReturnTime = 15.0;
new Float:fThrowingForce = 60000000.0;

public Plugin:myinfo= 
{
	name="PowerupsXL Medic",
	author="Skydive",
	description="PowerupsX Medic Ability",
	version="1.0",
	url=""
};


public OnMapStart()
{
	PrecacheModel("models/props_lab/monitor01a.mdl",true);
	AddFileToDownloadsTable("sound/custom/skydive/hax.mp3");
	PrecacheSound("custom/skydive/hax.mp3",true);
}

public OnPluginStart()
{
	NativeIncStart();
	
	AbilityHax = PX_RegisterAbility("AbilityHax");
	PX_SetAbilityName(AbilityHax,"Hax");
	PX_SetAbilityDescription(AbilityHax,"Recharge: 15-Level/10.");
	PX_SetAbilityUsage(AbilityHax,"Knife fires a Monitor.");
	PX_SetAbilityMaxLevel(AbilityHax,10);

	HookEvent("weapon_fire",Event_WeaponFire);
}

public PXF_OnAbilityGiven(Client, Ability)
{
	if(Ability == AbilityHax)
	{
		AbilityHaxUse[Client] = true;
	}
}

public Action:Event_WeaponFire(Handle:event, const String:name[],bool:dontBroadcast)
{
	decl String:sWeapon[30];
	GetEventString(event,"weapon",sWeapon,30);
	new userid = GetClientOfUserId(GetEventInt(event,"userid"));
	new Level = PX_GetLevel(userid, PX_GetAbility(userid));
	
	if(PX_GetAbility(userid) == AbilityHax && AbilityHaxUse[userid] == true)
	{
		if(StrEqual(sWeapon, "knife"))
		{	
			if(IsFakeClient(userid))
			{
				return;
			}
			
			new Float:fPlayerPos[3];
			new Float:fPlayerAngles[3];
			new Float:fThrowingVector[3];
			new Float:fDistanceFromSpawner = 40.0;
			
			GetClientEyeAngles( userid, fPlayerAngles );
			GetClientEyePosition( userid, fPlayerPos );
			
			TR_TraceRayFilter( fPlayerPos, fPlayerAngles, MASK_SOLID, RayType_Infinite, DontHitSelf, userid );
			
			if( TR_DidHit( ) )
			{
				new Float:fEndPosition[3];
				
				TR_GetEndPosition( fEndPosition );
				
				if( GetVectorDistance( fPlayerPos, fEndPosition ) < fDistanceFromSpawner )
				{
					return;
				}
			}
			
			EmitAmbientSound( "custom/skydive/hax.mp3", fPlayerPos, userid ); 
			
			new Float:fLen = fDistanceFromSpawner * Sine( DegToRad( fPlayerAngles[0] + 90.0 ) );
			
			fPlayerPos[0] = fPlayerPos[0] + fLen * Cosine( DegToRad( fPlayerAngles[1] ) );
			fPlayerPos[1] = fPlayerPos[1] + fLen * Sine( DegToRad( fPlayerAngles[1] ) );
			fPlayerPos[2] = fPlayerPos[2] + fDistanceFromSpawner * Sine( DegToRad( -1 * fPlayerAngles[0] ) ) ;
			
			new entity = CreateEntityByName( "prop_physics_override" );
	
			DispatchKeyValue( entity, "model", "models/props_lab/monitor01a.mdl" );
			DispatchKeyValue( entity, "massScale", "1.5" );
			DispatchKeyValue( entity, "spawnflags", "6" );
			
			DispatchSpawn( entity );
			ActivateEntity( entity );
			
			new Float:fScal = fThrowingForce * Sine( DegToRad( fPlayerAngles[0] + 90.0 ) );
			
			fThrowingVector[0] = fScal * Cosine( DegToRad( fPlayerAngles[1] ) );
			fThrowingVector[1] = fScal * Sine( DegToRad( fPlayerAngles[1] ) );
			fThrowingVector[2] = fThrowingForce * Sine( DegToRad( -1 * fPlayerAngles[0] ) );
			
			TeleportEntity( entity, fPlayerPos, fPlayerAngles, fThrowingVector );
			SetEntProp(entity, Prop_Send, "m_CollisionGroup", 1);
			SetEntProp(entity, Prop_Send, "m_usSolidFlags", 8);
			
			
			SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", userid);
			SDKHook(entity, SDKHook_TouchPost, StartHaxTouchPost);
			
			AbilityHaxUse[userid] = false;
			
			CreateTimer( HaxReturnTime-Level/10, DestroyTimer, entity );
			AbilityHaxTimer[userid] = CreateTimer( HaxReturnTime-Level/10, ReturnTimer, userid );
		}
	}
}

public Action:DestroyTimer( Handle:hTimer, any:edict )
{
	if(IsValidEntity(edict))
	{
		new String:dname[32], ent = CreateEntityByName("env_entity_dissolver");
		
		Format(dname, sizeof(dname), "dis_%d", edict);
		  
		if (ent > 0)
		{
			DispatchKeyValue(edict, "targetname", dname);
			DispatchKeyValue(ent, "dissolvetype", "3");
			DispatchKeyValue(ent, "target", dname);
			AcceptEntityInput(ent, "Dissolve");
			AcceptEntityInput(ent, "kill");
		}
	}
	return Plugin_Continue;
}

public Action:ReturnTimer( Handle:hTimer, any:Client )
{
	AbilityHaxUse[Client] = true;
	PrintHintText(Client,"Hax Returned!");
	return Plugin_Continue;
}

public Event_PlayerDeath(Handle:event, const String:name[],bool:dontBroadcast)
{
	new userid = GetClientOfUserId(GetEventInt(event,"victim"));
	if(AbilityHaxTimer[userid] != INVALID_HANDLE)
	{
		KillTimer(AbilityHaxTimer[userid]);
	}
}

public StartHaxTouchPost(entity, other)
{
	if(other > 0 && other <= MaxClients)
	{
		new Owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
	
		if(GetClientTeam(Owner) != GetClientTeam(other))
		{
			if(IsValidEntity(entity))
			{
				new String:dname[32], ent = CreateEntityByName("env_entity_dissolver");
				
				Format(dname, sizeof(dname), "dis_%d", entity);
				  
				if (ent > 0)
				{
					DispatchKeyValue(entity, "targetname", dname);
					DispatchKeyValue(ent, "dissolvetype", "3");
					DispatchKeyValue(ent, "target", dname);
					AcceptEntityInput(ent, "Dissolve");
					AcceptEntityInput(ent, "kill");
				}
			}
			SlapPlayer(other,100,false);
			SetEntProp(Owner, Prop_Data, "m_iFrags", GetEntProp(Owner, Prop_Data, "m_iFrags")+1);
		}
	}
}

public bool:DontHitSelf( entity, mask, any:data )
{
	if( entity == data )
	{
		return false;
	}
	
	return true;
}